package com.enseirb.bdxmap.dao.parser;

import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import com.enseirb.bdxmap.dao.dto.AbstractMarkerDTO;
import com.enseirb.bdxmap.exception.UndefinedIdMarkerException;
import com.enseirb.bdxmap.exception.UnlocalisableMarkerException;

public abstract class AbstractMarkerParser<T extends AbstractMarkerDTO> {
	protected String json_key_id;
	protected String json_key_long;
	protected String json_key_lat;
	protected String json_key_name;
	protected String default_marker_name;
	protected AbstractMarkerDTO currentServiceDTO;
	
	public List<T> createDTO(String serviceJson) {
		try {
			JSONObject serviceAsJson = (JSONObject) new JSONParser().parse(serviceJson);
			return createDTOFromJson(serviceAsJson);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private List<T> createDTOFromJson(
			JSONObject servicesJson) {	
		List<T> servicesDTO = new ArrayList<T>();
		JSONArray serviceArray = (JSONArray) servicesJson.get("d");
		for(int i = 0 ; i < serviceArray.size(); i++) {
			JSONObject serviceJson = (JSONObject) serviceArray.get(i);
			T serviceDTO = newServiceDTO();
			try {
				serviceDTO.id = getIdFromJson(serviceJson);
				serviceDTO.latitude = getLatitudeFromJson(serviceJson);
				serviceDTO.longitude = getLongitudeFromJson(serviceJson);
				serviceDTO.name = getNameFromJson(serviceJson);
				serviceDTO = getCustomFieldsFromJson(serviceDTO, serviceJson);
				servicesDTO.add(serviceDTO);
			} catch(UnlocalisableMarkerException e) {
				System.err.println("Got an unlocalisable marker, not added in the DTO list.");
			} catch(UndefinedIdMarkerException e) {
				System.err.println("Could not parse a marker's id, not added in the DTO list.");
			}
		}
		return servicesDTO;
	}

	protected abstract T newServiceDTO();
	
	private String getIdFromJson(JSONObject serviceJson) throws UndefinedIdMarkerException {
		if(serviceJson.containsKey(json_key_id)) {
			return serviceJson.get(json_key_id).toString();
		} else {
			throw new UndefinedIdMarkerException();
		}
	}

	private String getLongitudeFromJson(JSONObject serviceJson) throws UnlocalisableMarkerException {
		if(serviceJson.containsKey(json_key_long)) {
			return serviceJson.get(json_key_long).toString();
		} else {
			throw new UnlocalisableMarkerException();
		}
	}

	private String getLatitudeFromJson(JSONObject serviceJson) throws UnlocalisableMarkerException {
		if(serviceJson.containsKey(json_key_lat)) {
			return serviceJson.get(json_key_lat).toString();
		} else {
			throw new UnlocalisableMarkerException();
		}
	}

	private String getNameFromJson(JSONObject serviceJson) {
		if(serviceJson.containsKey(json_key_name)) {
			return serviceJson.get(json_key_name).toString();
		} else {
			return default_marker_name;
		}
	}
	
	protected abstract T getCustomFieldsFromJson(T serviceDTO, JSONObject serviceJson);
}